package vload

import (
	"fmt"
	"reflect"
)

// AddMapping 添加字段映射和对应的值获取器
func (l *Loader) AddMapping(group string, pairs []Pair, getter interface{}) {
	// 设置默认类型
	for i := range pairs {
		if pairs[i].SourceType == reflect.Invalid {
			pairs[i].SourceType = reflect.Int64
		}
		if pairs[i].TargetType == reflect.Invalid {
			pairs[i].TargetType = reflect.String
		}
		pairs[i].Group = group
	}

	l.pairs[group] = pairs
	l.getters[group] = getter
}

// Load 加载数据
func (l *Loader) Load(data interface{}) error {
	val := reflect.ValueOf(data)
	if val.Kind() != reflect.Ptr {
		return fmt.Errorf("data must be a pointer")
	}
	val = val.Elem()

	// 根据数据类型选择处理方法
	switch val.Kind() {
	case reflect.Struct:
		return l.loadStruct(val)
	case reflect.Slice:
		return l.loadSlice(val)
	default:
		return fmt.Errorf("unsupported data type: %v", val.Kind())
	}
}

// hasValidPairs 检查结构体是否包含任何有效的字段映射对
func (l *Loader) hasValidPairs(typ reflect.Type) bool {
	validPairsByGroup := l.getValidPairs(typ)
	for _, pairs := range validPairsByGroup {
		if len(pairs) > 0 {
			return true
		}
	}
	return false
}

// getValidPairs 获取结构体中有效的字段映射对，按分组返回
func (l *Loader) getValidPairs(typ reflect.Type) map[string][]Pair {
	result := make(map[string][]Pair)
	for group, pairs := range l.pairs {
		var validPairs []Pair
		for _, pair := range pairs {
			if _, hasSource := typ.FieldByName(pair.SourceField); hasSource {
				if _, hasTarget := typ.FieldByName(pair.TargetField); hasTarget {
					validPairs = append(validPairs, pair)
				}
			}
		}
		if len(validPairs) > 0 {
			result[group] = validPairs
		}
	}
	return result
}

// loadSlice 加载切片数据
func (l *Loader) loadSlice(slice reflect.Value) error {
	if slice.Len() == 0 {
		return nil
	}

	// 获取切片元素类型
	elemType := slice.Type().Elem()
	// 如果是指针类型，获取指针指向的类型
	if elemType.Kind() == reflect.Ptr {
		elemType = elemType.Elem()
	}
	if elemType.Kind() != reflect.Struct {
		return fmt.Errorf("slice element must be struct type or pointer to struct type")
	}

	// 检查是否有有效的字段映射对
	if !l.hasValidPairs(elemType) {
		return nil
	}

	// 获取有效的字段映射对
	validPairsByGroup := l.getValidPairs(elemType)

	// 收集所有键
	keysByGroup := make(map[string]map[interface{}]struct{})
	for i := 0; i < slice.Len(); i++ {
		elem := slice.Index(i)
		// 如果是指针类型，获取指针指向的值
		if elem.Kind() == reflect.Ptr {
			elem = elem.Elem()
		}
		l.collectKeys(elem, keysByGroup, validPairsByGroup)
	}

	// 处理每个分组
	for group, keys := range keysByGroup {
		// 转换键为列表
		var keyList []interface{}
		for key := range keys {
			keyList = append(keyList, key)
		}

		getter := l.getters[group]
		valueMap, err := callGetter(getter, keyList)
		if err != nil {
			return err
		}

		// 填充值
		validPairs := validPairsByGroup[group]
		for i := 0; i < slice.Len(); i++ {
			elem := slice.Index(i)
			// 如果是指针类型，获取指针指向的值
			if elem.Kind() == reflect.Ptr {
				elem = elem.Elem()
			}
			l.fillValues(elem, valueMap, validPairs)
		}
	}

	return nil
}

// loadStruct 加载单个结构体
func (l *Loader) loadStruct(val reflect.Value) error {
	// 检查是否有有效的字段映射对
	if !l.hasValidPairs(val.Type()) {
		return nil
	}

	// 获取有效的字段映射对
	validPairsByGroup := l.getValidPairs(val.Type())

	// 收集所有键
	keysByGroup := make(map[string]map[interface{}]struct{})
	l.collectKeys(val, keysByGroup, validPairsByGroup)

	// 处理每个分组
	for group, keys := range keysByGroup {
		// 转换键为列表
		var keyList []interface{}
		for key := range keys {
			keyList = append(keyList, key)
		}

		getter := l.getters[group]
		valueMap, err := callGetter(getter, keyList)
		if err != nil {
			return err
		}

		l.fillValues(val, valueMap, validPairsByGroup[group])
	}

	return nil
}
